﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PACKETPARSERMAX20.CORE
{
    public class DefinitionProcessor : IDisposable
    {
        public WoWCore Core { get; private set; }
        public ReaderBase Reader { get; private set; }
        public OpcodeFilter OpcodeFilter { get; private set; }
        public List<uint> UniqueOpcodeList { get; private set; }
        public List<uint> DefinedOpcodeList { get; private set; }
        public EventManager EventManager { get; private set; }

        public DefinitionProcessor(ReaderBase reader, EventManager eventmanager, OpcodeFilter opcodefilter)
        {
            Reader = reader;
            OpcodeFilter = opcodefilter;
            EventManager = eventmanager;
            Core = new WoWCore(eventmanager);
            UniqueOpcodeList = new List<uint>();
            DefinedOpcodeList = new List<uint>();
        }

        public void Reset()
        {
            Core = new WoWCore(EventManager);
            Reader.Close();
        }
        public void Process()
        {
            Process(false, "");
        }

        public void Process(bool resume)
        {
            Process(resume);
        }
        public void Process(string query)
        {
            Process(false, query);
        }

        public List<uint> SpellInfoIdList
        {
            get
            {
                return GlobalCache.m_spellInfoIdList;
            }
        }
        public void Process(bool resume, string query)
        {
            int index = 0;

            if (!resume)
            {
                Reader.Load(query);
            }

            EventManager.UpdateStatusLog(System.DateTime.Now.ToString(), "Processing Started... ", false, 2);


            //iterate through log bytes
            while (true)
            {
                if (EventManager.Pause) { break; }

                var packet = Reader.GetNextPacket();

                if (packet != null)
                {
                    if (!OpcodeFilter.Contains((Opcodes)packet.Opcode))
                    {
                        if (!DefinedOpcodeList.Contains(packet.Opcode) && !UniqueOpcodeList.Contains(packet.Opcode))
                        {
                            EventManager.UpdateStatusLog(System.DateTime.Now.ToString(), string.Format("Unique Opcode: {0}\t{1}", packet.OpcodeName, packet.Opcode), false, 0);
                            UniqueOpcodeList.Add(packet.Opcode);
                        }

                        var tContext = new DefinitionContext(packet, Reader, Core, DefinedOpcodeList);

                        var tDef = tContext.GetDefinition();

                      
                        tDef.Process();

                        index = packet.Id;

                        if (!EventManager.SilentMode) { EventManager.Object_Updated(packet); }

                        if (packet.Result.Length > 0)
                        {
                            EventManager.UpdateWarning(packet.Result.ToString());
                        };
                    }
                    else
                    {
                        EventManager.UpdateStatusLog(System.DateTime.Now.ToString(), string.Format("Filtered Opcode: {0}\t{1}", packet.OpcodeName, packet.Opcode), false, 0);
                        packet.Result.AppendLine("Filtered");
                    }

                }
                else
                {
                    break;
                }
            }

            EventManager.CurrentPacketIndex(index);

            EventManager.UpdateStatusLog(System.DateTime.Now.ToString(), "Processing Completed... ", false, 2);
        }

        public static DefinitionProcessor LoadDefinitionProcessor(string file, EventManager eventmanager, OpcodeFilter opcodefilter)
        {
            var reader = ReaderHelper.GetReaderForFile(file);

            if (reader != null)
            {
                return new DefinitionProcessor(reader, eventmanager, opcodefilter);
            }

            return null;
        }

        void IDisposable.Dispose()
        {

            (Reader as IDisposable).Dispose();
        }
    }
}
